package com.kakame.tibbers;

import java.time.Duration;

import com.alibaba.druid.filter.logging.Slf4jLogFilter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.wall.WallFilter;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.ext.handler.ContextPathHandler;
import com.jfinal.ext.interceptor.SessionInViewInterceptor;
import com.jfinal.log.ILogFactory;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.template.Engine;
import com.jfinal.template.ext.directive.NowDirective;
import com.kakame.tibbers.common.directive.AuthDirective;
import com.kakame.tibbers.common.directive.ResourceNameDirective;
import com.kakame.tibbers.common.directive.ResourceUrlDirective;
import com.kakame.tibbers.common.init.FastdfsConfig;
import com.kakame.tibbers.common.init.cache.ResourceCache;
import com.kakame.tibbers.common.init.cache.UserCache;
import com.kakame.tibbers.common.interceptors.GlobalActionInterceptor;
import com.kakame.tibbers.common.models._MappingKit;
import com.kakame.tibbers.common.routes.AdminRoutes;
import com.kakame.tibbers.common.routes.FrontRoutes;
import com.kakame.tibbers.common.utils.LoggerUtil;
import com.kakame.tibbers.common.utils.PropUtil;

public class App extends JFinalConfig {
	public void configConstant(Constants me) {
		// 在开发模式下，JFinal会对每次请求输出报告，如输出本次请求的URL、Controller、Method以及请求所携带的参数。
		me.setDevMode(PropUtil.APP.getBoolean("app.devMode"));
		// log4j2配置
		me.setLogFactory(new ILogFactory() {

			@Override
			public Log getLog(String name) {
				return LoggerUtil.Logger;
			}

			@Override
			public Log getLog(Class<?> clazz) {
				return LoggerUtil.Logger;
			}
		});
	}

	public void configRoute(Routes me) {
		me.add(new FrontRoutes()); // 前端路由
		me.add(new AdminRoutes()); // 后端路由
	}

	public void configEngine(Engine me) {
		// 全局变量
		me.addSharedObject("siteTitle", PropUtil.APP.get("app.siteTitle"));
		
		// 指令
		// 时间戳
		me.addDirective("now", NowDirective.class);
		// 权限标签
		me.addDirective("auth", AuthDirective.class);
		// 获取资源url标签
		me.addDirective("resUrl", ResourceUrlDirective.class);
		// 获取资源name标签
		me.addDirective("resName", ResourceNameDirective.class);
		
		// 前台模版
		me.addSharedFunction("/WEB-INF/views/front/include/layout.html");
		// 后台模版
		me.addSharedFunction("/WEB-INF/views/admin/include/frame_layout.html");
		me.addSharedFunction("/WEB-INF/views/admin/include/page_layout.html");
	}

	public void configPlugin(Plugins me) {
		// *** 数据库连接池
		DruidPlugin dp = createDruidPlugin();
		me.add(dp);

		// *** 数据库映射
		ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
		// 所有映射在 MappingKit 中自动化搞定
		_MappingKit.mapping(arp);
		me.add(arp);
	}

	public static DruidPlugin createDruidPlugin() {
		DruidPlugin druidPlugin = new DruidPlugin(PropUtil.APP.get("jdbc.url"), PropUtil.APP.get("jdbc.username"),
				PropUtil.APP.get("jdbc.password"));
		// 添加数据库插件
		// 1.统计信息插件
		StatFilter statFilter = new StatFilter();
		statFilter.setMergeSql(true);
		statFilter.setLogSlowSql(true);
		// 慢查询目前设置为1s,随着优化一步步进行慢慢更改
		statFilter.setSlowSqlMillis(Duration.ofMillis(1000).toMillis());
		druidPlugin.addFilter(statFilter);
		// 2.日志插件
		// 保存DruidDataSource的监控记录,设置打印日志周期,默认使用DruidDataSourceStatLoggerImpl
		// DruidPlugin未暴露setTimeBetweenLogStatsMillis(),只能使用properties方法设置
		druidPlugin.setConnectionProperties("druid.timeBetweenLogStatsMillis=" + Duration.ofHours(24).toMillis());
		Slf4jLogFilter slf4jLogFilter = new Slf4jLogFilter();
		slf4jLogFilter.setDataSourceLogEnabled(false);
		slf4jLogFilter.setConnectionLogEnabled(false);
		slf4jLogFilter.setConnectionLogErrorEnabled(true);
		slf4jLogFilter.setStatementLogEnabled(false);
		slf4jLogFilter.setStatementLogErrorEnabled(true);
		slf4jLogFilter.setResultSetLogEnabled(false);
		slf4jLogFilter.setResultSetLogErrorEnabled(true);
		slf4jLogFilter.setConnectionConnectBeforeLogEnabled(false);
		slf4jLogFilter.setConnectionConnectAfterLogEnabled(false);
		slf4jLogFilter.setConnectionCommitAfterLogEnabled(false);
		slf4jLogFilter.setConnectionRollbackAfterLogEnabled(true);
		slf4jLogFilter.setConnectionCloseAfterLogEnabled(false);
		slf4jLogFilter.setStatementCreateAfterLogEnabled(false);
		slf4jLogFilter.setStatementPrepareAfterLogEnabled(false);
		slf4jLogFilter.setStatementPrepareCallAfterLogEnabled(false);
		slf4jLogFilter.setStatementExecuteAfterLogEnabled(false);
		slf4jLogFilter.setStatementExecuteQueryAfterLogEnabled(false);
		slf4jLogFilter.setStatementExecuteUpdateAfterLogEnabled(false);
		slf4jLogFilter.setStatementExecuteBatchAfterLogEnabled(false);
		slf4jLogFilter.setStatementCloseAfterLogEnabled(false);
		slf4jLogFilter.setStatementParameterSetLogEnabled(false);
		slf4jLogFilter.setResultSetNextAfterLogEnabled(false);
		slf4jLogFilter.setResultSetOpenAfterLogEnabled(false);
		slf4jLogFilter.setResultSetCloseAfterLogEnabled(false);
		slf4jLogFilter.setStatementExecutableSqlLogEnable(PropUtil.APP.getBoolean("druid.showSql", false));
		druidPlugin.addFilter(slf4jLogFilter);
		// 3.防注入插件
		WallFilter wall = new WallFilter();
		wall.setDbType("mysql");
		druidPlugin.addFilter(wall);
		return druidPlugin;
	}

	public void configInterceptor(Interceptors me) {
		// 全局控制层的拦截器
		me.addGlobalActionInterceptor(new GlobalActionInterceptor());
		// 页面用session
		me.add(new SessionInViewInterceptor());
	}

	public void configHandler(Handlers me) {
		me.add(new ContextPathHandler("ctx"));
	}

	// 系统启动完成后回调
	public void afterJFinalStart() {
		// 加载fastdfs配置文件
		FastdfsConfig.init();
		// 加载用户，这个一定要在权限之前
		UserCache.me.init();
		// 加载权限
		ResourceCache.me.init();
	}

	// 系统关闭之前回调
	public void beforeJFinalStop() {
	}
}